﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;

namespace HYFloorPipeModule
{
	public class MixPair
	{
		public MixPair(XYZ pts, XYZ pte, bool isin = false)
		{
			this.isArc = false;
			this.isIn = isin;
			this.ptstart = pts;
			this.ptend = pte;
			this.pointPair = new PointPair(pts, pte, isin, false);
		}

		public MixPair(Arc arc, bool isin = false)
		{
			this.isArc = true;
			this.isIn = isin;
			this.ptstart = arc.GetEndPoint(0);
			this.ptend = arc.GetEndPoint(1);
			XYZ xyzpoint = arc.Project(0.5 * (this.ptstart + this.ptend)).XYZPoint;
			this.arcptPair = new ArcPtPair(this.ptstart, xyzpoint, this.ptend, this.isIn, false);
		}

		public MixPair(XYZ pts, XYZ ptm, XYZ pte, bool isin = false)
		{
			this.isArc = true;
			this.isIn = isin;
			this.ptstart = pts;
			this.ptend = pte;
			this.arcptPair = new ArcPtPair(pts, ptm, pte, isin, false);
		}

		public MixPair(MixPair mp)
		{
			this.isArc = mp.IsArc;
			this.isIn = mp.IsIn;
			if (mp.IsArc)
			{
				this.arcptPair = new ArcPtPair(mp.Start, mp.Mid, mp.End, mp.IsIn, false);
				return;
			}
			this.pointPair = new PointPair(mp.Start, mp.End, mp.IsIn, false);
		}

		public XYZ Start
		{
			get
			{
				if (!this.isArc)
				{
					return this.pointPair.First;
				}
				return this.arcptPair.Start;
			}
			set
			{
				this.ptstart = value;
				if (this.isArc)
				{
					this.arcptPair.Start = value;
					return;
				}
				this.pointPair.First = value;
			}
		}

		public XYZ End
		{
			get
			{
				if (!this.isArc)
				{
					return this.pointPair.Second;
				}
				return this.arcptPair.End;
			}
			set
			{
				this.ptend = value;
				if (this.isArc)
				{
					this.arcptPair.End = value;
					return;
				}
				this.pointPair.Second = value;
			}
		}

		public XYZ Mid
		{
			get
			{
				if (!this.isArc)
				{
					return 0.5 * (this.pointPair.Second + this.pointPair.First);
				}
				return this.arcptPair.Mid;
			}
		}

		public bool IsIn
		{
			get
			{
				return this.isIn;
			}
			set
			{
				this.isIn = value;
				if (this.isArc)
				{
					this.arcptPair.IsIn = value;
					return;
				}
				this.pointPair.IsIn = value;
			}
		}

		public bool IsArc
		{
			get
			{
				return this.isArc;
			}
		}

		public void Offset(XYZ vec)
		{
			if (this.isArc)
			{
				this.ArcaOffset(vec);
				return;
			}
			this.pointPair.Offset(vec);
		}

		public double DistanceTo(MixPair mp)
		{
			Curve curve = mp.CreateCurve();
			curve.MakeUnbound();
			return this.Start.DistanceTo(curve.Project(this.Start).XYZPoint);
		}

		private void ArcaOffset(XYZ vec)
		{
			Arc arc = this.arcptPair.CreateArc();
			XYZ center = arc.Center;
			XYZ xyz = 0.5 * (this.arcptPair.Start + this.arcptPair.End);
			XYZ xyz2 = (center - xyz).Normalize();
			double length = vec.GetLength();
			double num;
			if (xyz2.IsAlmostEqualTo(vec.Normalize()))
			{
				num = arc.Radius - length;
			}
			else
			{
				if (!xyz2.IsAlmostEqualTo(-vec.Normalize()))
				{
					return;
				}
				num = arc.Radius + length;
			}
			this.ptstart = center + (this.arcptPair.Start - center).Normalize() * num;
			this.ptend = center + (this.arcptPair.End - center).Normalize() * num;
			this.arcptPair.Start = this.ptstart;
			this.arcptPair.End = this.ptend;
			this.arcptPair.Mid = center - xyz2 * num;
		}

		public double GetLength()
		{
			if (!this.isArc)
			{
				return this.pointPair.GetLength();
			}
			return this.arcptPair.CreateArc().Length;
		}

		public XYZ AsVector()
		{
			if (!this.isArc)
			{
				return this.pointPair.AsVector().Normalize();
			}
			return (this.arcptPair.End - this.arcptPair.Start).Normalize();
		}

		public void Retract(double dFirst, double dEnd)
		{
			if (this.isArc)
			{
				this.arcptPair.Retract(dFirst, dEnd);
				this.ptstart = this.arcptPair.Start;
				this.ptend = this.arcptPair.End;
				return;
			}
			this.pointPair.Retract(dFirst, dEnd);
			this.ptstart = this.pointPair.First;
			this.ptend = this.pointPair.Second;
		}

		public Curve CreateCurve()
		{
			if (!this.isArc)
			{
				return this.pointPair.CreateLine();
			}
			return this.arcptPair.CreateArc();
		}

		public void DoExchange()
		{
			if (this.isArc)
			{
				this.arcptPair.DoExchange();
				return;
			}
			this.pointPair.DoExchange();
		}

		public bool HasIntersectionTo(MixPair mp2)
		{
			if (this.isArc || mp2.IsArc)
			{
				return false;
			}
			Curve curve = this.CreateCurve();
			Curve curve2 = mp2.CreateCurve();
			List<XYZ> list = new List<XYZ>();
			IntersectionResultArray intersectionResultArray = new IntersectionResultArray();
			SetComparisonResult setComparisonResult = curve.Intersect(curve2, out intersectionResultArray);
			if (4 != (int)setComparisonResult && intersectionResultArray != null && !intersectionResultArray.IsEmpty)
			{
				for (int i = 0; i < intersectionResultArray.Size; i++)
				{
					list.Add(intersectionResultArray.get_Item(i).XYZPoint);
				}
			}
			return list.Count != 0;
		}

		public bool IsParallel(MixPair mp2)
		{
			if (this.isArc || mp2.IsArc)
			{
				return false;
			}
			XYZ xyz = this.AsVector();
			XYZ xyz2 = mp2.AsVector();
			return xyz.IsAlmostEqualTo(xyz2) || xyz.IsAlmostEqualTo(-xyz2);
		}

		public bool IsCollinearWith(MixPair mp2)
		{
			if (this.isArc && mp2.IsArc)
			{
				Arc arc = this.CreateCurve() as Arc;
				Arc arc2 = mp2.CreateCurve() as Arc;
				return arc.Center.IsAlmostEqualTo(arc2.Center) && arc.Radius == arc2.Radius;
			}
			if (!this.isArc && !mp2.IsArc)
			{
				XYZ xyz = (this.Start - mp2.Start).Normalize();
				return this.IsParallel(mp2) && (this.AsVector().IsAlmostEqualTo(xyz) || this.AsVector().IsAlmostEqualTo(-xyz));
			}
			return false;
		}

		private PointPair pointPair;

		private ArcPtPair arcptPair;

		private bool isArc;

		private bool isIn;

		private XYZ ptstart;

		private XYZ ptend;
	}
}
